import { createMachine } from "xstate";

export const coreMachine = createMachine({
  context: {},
  id: "Core",
  initial: "uninit",
  states: {
    uninit: {
      on: {
        start_init: {
          target: "init",
          actions: {
            type: "init",
          },
        },
      },
      entry: {
        type: "uninit_entry",
      },
      exit: {
        type: "uninit_exit",
      },
    },
    init: {
      on: {
        start_login: {
          target: "connect_network",
          actions: {
            type: "on_start_login",
          },
        },
      },
      entry: {
        type: "init_entry",
      },
      exit: {
        type: "init_exit",
      },
    },
    connect_network: {
      entry: {
        type: "connect_entry",
      },
      exit: {
        type: "connect_exit",
      },
      invoke: {
        id: "connect_server",
        input: ({context, event: {loginParam}}) => ({loginParam}),
        onDone: {
          target: "logining",
          actions: {
            type: "on_connect_done",
          },
        },
        onError: [
          {
            target: "wait_net_disconnected",
            actions: {
              type: "on_connect_error_and_try",
            },
            guard: {
              type: "can_retry_connect",
            },
          },
          {
            target: "init",
            actions: {
              type: "on_connect_error",
            },
          },
        ],
        src: "connect",
      },
    },
    logining: {
      on: {
        send_event: {
          target: "logining",
          actions: {
            type: "send_event",
          },
        },
      },
      entry: {
        type: "logining_entry",
      },
      exit: {
        type: "logining_exit",
      },
      invoke: {
        id: "login_server",
        input: ({context, event: {output}}) => ({loginParam: output}),
        onDone: {
          target: "ready",
          actions: {
            type: "on_login_done",
          },
        },
        onError: [
          {
            target: "wait_net_disconnected",
            actions: {
              type: "on_login_error_and_try",
            },
            guard: {
              type: "should_try_login",
            },
          },
          {
            target: "init",
            actions: {
              type: "on_login_error",
            },
          },
        ],
        src: "login",
      },
    },
    wait_net_disconnected: {
      on: {
        relogin: {
          target: "connect_network",
          actions: {
            type: "on_relogin",
          },
        },
      },
      entry: {
        type: "on_wait_net_disconnected_entry",
      },
      exit: {
        type: "on_wait_net_disconnected_exit",
      },
    },
    ready: {
      on: {
        send_event: {
          target: "ready",
          actions: {
            type: "send_event",
          },
        },
        server_kickout_ind: {
          target: "init",
          actions: {
            type: "on_server_kickout",
          },
        },
        log_out: {
          target: "logging_out",
          actions: {
            type: "on_log_out",
          },
        },
        reset_network: {
          target: "disconnect_network",
          actions: {
            type: "on_reset_network",
          },
        },
        network_disconnect: {
          target: "wait_net_disconnected",
          actions: {
            type: "on_network_disconnect",
          },
        },
      },
      entry: {
        type: "ready_entry",
      },
      exit: {
        type: "ready_exit",
      },
    },
    logging_out: {
      on: {
        send_event: {
          target: "logging_out",
          actions: {
            type: "send_event",
          },
        },
      },
      invoke: {
        id: "log_out_server",
        input: ({context, event: {logoutParam}}) => ({logoutParam}),
        onDone: {
          target: "init",
          actions: {
            type: "onLogoutDone",
          },
        },
        onError: {
          target: "init",
          actions: {
            type: "onLogoutFailed",
          },
        },
        src: "logout_server",
      },
    },
    disconnect_network: {
      invoke: {
        id: "disconnect_network",
        input: {},
        onDone: {
          target: "init",
          actions: {
            type: "on_disconnect_done",
          },
        },
        onError: {
          target: "init",
          actions: {
            type: "on_disconnect_failed",
          },
        },
        src: "disconnect_network",
      },
    },
  },
});